﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace CSharpHelpers.Encrypts
{
    class AESEncryptHelper
    {
        #region
        private static readonly string Key = "LTgame2015PassWordGeNIus11808899";

        public delegate void EncryptErrorHandle(Exception e);

        /// <summary>
        /// 异常事件
        /// </summary>
        public static EncryptErrorHandle OnError;

        /// <summary>
        /// AES加密算法
        /// </summary>
        /// <param name="toEncrypt">明文字符串</param>
        /// <param name="isDefaultKey">是否使用LTgame默认Key</param>
        /// <param name="strKey">自定义Key</param>
        /// <returns>返回加密后的密文字,返回空为解密无效</returns>
        public static string AESEncrypt(string toEncrypt, bool isDefaultKey = true, string strKey = null)
        {
            try
            {
                if (isDefaultKey)
                {
                    strKey = Key;
                }

                //// 256-AES key    
                byte[] keyArray = Encoding.UTF8.GetBytes(strKey);
                byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);

                RijndaelManaged rDel = new RijndaelManaged();
                rDel.Key = keyArray;
                rDel.Mode = CipherMode.ECB;
                rDel.Padding = PaddingMode.Zeros;

                ICryptoTransform cTransform = rDel.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return ByteToHex(resultArray);
            }
            catch (Exception ex)
            {
                if (OnError != null)
                {
                    OnError(ex);
                }

                return string.Empty;
            }

        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="toDecrypt">要解密内容</param>
        /// <param name="isDefaultKey">是否使用LTgame默认Key</param>
        /// <param name="strKey">自定义Key</param>
        /// <returns>返回解密后的字符串,返回空为解密无效</returns>
        public static string AESDecrypt(string toDecrypt, bool isDefaultKey = true, string strKey = null)
        {
            try
            {
                if (isDefaultKey)
                {
                    strKey = Key;
                }

                // 256-AES key    
                byte[] keyArray = Encoding.UTF8.GetBytes(strKey);
                byte[] toEncryptArray = HexToByte(toDecrypt);
                if (toEncryptArray == null)
                {
                    return String.Empty;
                }

                RijndaelManaged rDel = new RijndaelManaged();
                rDel.Key = keyArray;
                rDel.Mode = CipherMode.ECB;
                rDel.Padding = PaddingMode.Zeros;

                ICryptoTransform cTransform = rDel.CreateDecryptor();
                byte[] tempArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                // 去掉后面补位的
                //var resultArray = tempArray.Where(b => b > 0).ToArray();// 3.5 或者以上框架可以用这个
                var resultArray = new List<byte>();
                foreach (byte b in tempArray)
                {
                    if (b > 0)
                    {
                        resultArray.Add(b);
                    }
                }

                var re = Encoding.UTF8.GetString(resultArray.ToArray());
                return re;
            }
            catch (Exception ex)
            {
                if (OnError != null)
                {
                    OnError(ex);
                }

                return string.Empty;
            }
        }

        public static Byte[] HexToByte(String szHex)
        {
            // 两个十六进制代表一个字节   
            Int32 iLen = szHex.Length;
            if (iLen <= 0 || 0 != iLen % 2)
            {
                return null;
            }
            Int32 dwCount = iLen / 2;
            UInt32 tmp1, tmp2;
            Byte[] pbBuffer = new Byte[dwCount];
            for (Int32 i = 0; i < dwCount; i++)
            {
                tmp1 = (UInt32)szHex[i * 2] - (((UInt32)szHex[i * 2] >= (UInt32)'A') ? (UInt32)'A' - 10 : (UInt32)'0');
                if (tmp1 >= 16) return null;
                tmp2 = (UInt32)szHex[i * 2 + 1] -
                       (((UInt32)szHex[i * 2 + 1] >= (UInt32)'A') ? (UInt32)'A' - 10 : (UInt32)'0');
                if (tmp2 >= 16) return null;
                pbBuffer[i] = (Byte)(tmp1 * 16 + tmp2);
            }
            return pbBuffer;
        }

        public static String ByteToHex(Byte[] vByte)
        {
            if (vByte == null || vByte.Length < 1) return null;
            StringBuilder sb = new StringBuilder(vByte.Length * 2);
            for (int i = 0; i < vByte.Length; i++)
            {
                if ((UInt32)vByte[i] < 0) return null;
                UInt32 k = (UInt32)vByte[i] / 16;
                sb.Append((Char)(k + ((k > 9) ? 'A' - 10 : '0')));
                k = (UInt32)vByte[i] % 16;
                sb.Append((Char)(k + ((k > 9) ? 'A' - 10 : '0')));
            }
            return sb.ToString();
        }

        #endregion
    }
}
